﻿using QFramework;
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
using System.Threading;
using UnityEngine;

#if NET_4_6
using System.IO.Ports;

namespace HKTools
{
    [Serializable]
    public class SerialConfig
    {
        public string PortName;
        public int BaudRate;
        public string Parity;
        public int DataBits;
        public string StopBits;
    }

    public interface IHK_SerialPortSystem : ISystem
    {
        /// <summary>
        /// 初始化 串口通信系统
        /// </summary>
        void InitSerialPort(int revLength);

        /// <summary>
        /// 扫描本机开启的串口
        /// </summary>
        /// <returns></returns>
        string[] ScanPorts();

        /// <summary>
        /// 开启串口
        /// </summary>
        void OpenSerialPort();

        /// <summary>
        /// 关闭串口
        /// </summary>
        void CloseSerialPort();
    }

    public class HK_SerialPortSystem : AbstractSystem, IHK_SerialPortSystem
    {
        ConcurrentQueue<string> dataQueue = new ConcurrentQueue<string>();

        SerialConfig config;
        SerialPort sp;

        bool isInit = false;
        int length = 6;

        protected override void OnInit()
        {

        }

        public void InitSerialPort(int revLength)
        {
            if (isInit) return;

            string path = Path.Combine(Application.streamingAssetsPath, "HK_SerialConfig.json");

            if (File.Exists(path))
            {
                string dataJson = File.ReadAllText(path);

                config = JsonUtility.FromJson<SerialConfig>(dataJson);

                Debug.Log("当前预链接串口号：" + config.PortName);
            }
            else
            {
                Debug.LogWarning("串口配置文件不存在!");

                return;
            }

            ActionKit.OnUpdate.Register(() =>
            {
                while (dataQueue.TryDequeue(out string data))
                {
                    this.SendEvent(new Event_ReceiveSerialPortData() { _serialPortData = data });
                }
            });

            length = revLength;
            isInit = true;
        }

        public string[] ScanPorts()
        {
            string[] portsList = SerialPort.GetPortNames();

            for (int i = 0; i < portsList.Length; i++)
            {
                Debug.Log(portsList[i]);
            }

            return portsList;
        }

        /// 打开串口
        /// </summary>
        /// <param name="_portName">端口号</param>
        /// <param name="_baudRate">波特率</param>
        /// <param name="_parity">校验位</param>
        /// <param name="dataBits">数据位</param>
        /// <param name="_stopbits">停止位</param>
        public void OpenSerialPort()
        {
            if (!isInit) return;

            try
            {
                Parity parity = Parity.None;

                switch (config.Parity.ToLower())
                {
                    case "none":
                        parity = Parity.None;
                        break;
                    case "mark":
                        parity = Parity.Mark;
                        break;
                    case "odd":
                        parity = Parity.Odd;
                        break;
                    case "space":
                        parity = Parity.Space;
                        break;
                    case "even":
                        parity = Parity.Even;
                        break;
                    default:
                        parity = Parity.None;
                        break;
                }

                StopBits stopbits = StopBits.None;

                switch (config.StopBits.ToLower())
                {
                    case "none":
                        stopbits = StopBits.None;
                        break;
                    case "one":
                        stopbits = StopBits.One;
                        break;
                    case "two":
                        stopbits = StopBits.Two;
                        break;
                    case "onepointfive":
                        stopbits = StopBits.OnePointFive;
                        break;
                    default:
                        stopbits = StopBits.None;
                        break;
                }

                sp = new SerialPort(config.PortName, config.BaudRate, parity, config.DataBits, stopbits);//绑定端口
                sp.Open();

                //使用线程接受 串口数据
                Thread thread = new Thread(new ThreadStart(DataReceived_Normal));
                thread.Start();

                Debug.Log("串口开启");
            }
            catch (Exception ex)
            {
                sp = new SerialPort();
                Debug.Log(ex);
            }
        }

        /// <summary>
        /// 接收数据 线程
        /// </summary>
        void DataReceived_Normal()
        {
            while (true)
            {
                if (sp.IsOpen)
                {
                    int count = sp.BytesToRead;

                    if (count >= length)
                    {
                        byte[] readBuffer = new byte[count];
                        try
                        {
                            sp.Read(readBuffer, 0, count);

                            //数据处理
                            StringBuilder sb = new StringBuilder();
                            for (int i = 0; i < readBuffer.Length; i++)
                            {
                                sb.AppendFormat("{0:x2}", readBuffer[i]);
                            }

                            dataQueue.Enqueue(sb.ToString());
                        }
                        catch (Exception ex)
                        {
                            Debug.Log(ex.Message);
                        }
                    }
                }
                Thread.Sleep(10);
            }
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        public void CloseSerialPort()
        {
            if (!isInit) return;

            if (sp == null) return;

            sp.Close();

            Debug.Log("串口关闭");
        }
    }
}
#endif